module qtwidgets

import os
import sync

import vqt.qtrt
import vqt.qtcore
import vqt.qtgui

/* pub fn new_qwidget_list_fromptr(cthis voidptr) QWidgetList { return QWidgetList{cthis} } */

/* pub fn new_qgraphics_item_list_fromptr(cthis voidptr) QGraphicsItemList { */
/*     return QGraphicsItemList{cthis} */
/* } */

struct TaskData {
    mut:
    f fn(voidptr)
    arg voidptr
}
struct Uitask {
    mut:
    qapp QApplication
    evtno int = 60123
    rcvobj qtcore.QObject
    seq i64 = 10000
    tasks []TaskData
    mu &sync.RwMutex = sync.new_rwmutex()

    // fix c argv
    argv [8]byteptr
}

fn (this &Uitask) put(td TaskData) {
    mut uitk2 := this
    uitk2.mu.w_lock()
    uitk2.tasks << td
    uitk2.mu.w_unlock()
}
fn (this &Uitask) pop() TaskData {
    mut uitk2 := this
    mut td := TaskData{}
    uitk2.mu.w_lock()
    if uitk2.tasks.len > 0 {
        td = uitk2.tasks[0]
        uitk2.tasks.delete(0)
    }
    uitk2.mu.w_unlock()
    return td
}

const uitk = Uitask{}

fn uitaskEventCallback(e voidptr) {
    mut uitk2 := &uitk
    println(e)
    eo := qtcore.newQEventFromptr(e)
    println(eo.type_())
}
fn setupUitaskHandler(qapp QApplication) {
    mut uitk2 := &uitk
    rcvobj := qtcore.newQObjectp()
    uitk2.rcvobj = rcvobj
    uitk2.qapp = qapp
    qtrt.setAllInheritCallback(rcvobj.get_cthis(), "event", uitaskEventCallback)
}

pub fn runonUithread(f fn(voidptr), arg voidptr) {
    td := TaskData{f, arg}
    mut uitk2 := &uitk
    uitk2.put(td)

    evt := qtcore.newQEvent0(uitk2.evtno)
    uitk2.qapp.QGuiApplication.postEventp(uitk2.rcvobj, evt)
}

fn vargv2c() voidptr {
    mut uitk2 := uitk
    for i := 0; i < os.args.len; i ++ {
        uitk2.argv[i] = &os.args[0]
        uitk2.argv[i+1] = byteptr(0)
    }
    return &uitk.argv[0]
}

type T_ZN12QApplicationC2ERiPPci = fn(cthis voidptr, argc &int, argv &byteptr, flag int)


pub fn newQApplication() QApplication {
    mut fnobj := T_ZN12QApplicationC2ERiPPci(0)
    fnobj = qtrt.sym_qtfunc6(0, "_ZN12QApplicationC2ERiPPci")
    cthis := qtrt.mallocraw(16)
    fnobj(cthis, &os.args.len, vargv2c(), 0)
    vthis := newQApplicationFromptr(cthis)
    setupUitaskHandler(vthis)
    return vthis
}

type T_ZN12QApplication4execEv = fn() int
pub fn (this QApplication) exec() int {
    mut fnobj := T_ZN12QApplication4execEv(0)
    fnobj = qtrt.sym_qtfunc6(0, "_ZN12QApplication4execEv")
    rv := fnobj()
    return rv
}

// sumtype as interface
pub type QWidgetITFx2 = QWidget | QPushButton | QAbstractButton | QLabel | QToolButton |
    QLineEdit | QPlainTextEdit | QComboBox | QMainWindow | QFrame

pub type QLayoutITFx2 = QLayout | QBoxLayout | QVBoxLayout | QHBoxLayout

pub fn (this QWidgetITFx2) get_cthis() voidptr {
    mut cthis := voidptr(0)
    match this {
        QWidget { cthis = this.get_cthis() }
        QPushButton { cthis = this.get_cthis() }
        QAbstractButton{ cthis = this.get_cthis() }
        QLabel { cthis = this.get_cthis() }
        QToolButton { cthis = this.get_cthis() }
        QLineEdit { cthis = this.get_cthis() }
        QPlainTextEdit { cthis = this.get_cthis() }
        QComboBox { cthis = this.get_cthis() }
        QMainWindow { cthis = this.get_cthis() }
        QFrame { cthis = this.get_cthis() }
    }
    return cthis
}

pub fn (this QLayoutITFx2) get_cthis() voidptr {
    mut cthis := voidptr(0)
    match this {
        QLayout { cthis = this.get_cthis() }
        QBoxLayout { cthis = this.get_cthis() }
        QHBoxLayout { cthis = this.get_cthis() }
        QVBoxLayout { cthis = this.get_cthis() }
    }
    return cthis
}

pub type SumofSumtype = QLayoutITFx2 | QWidgetITFx2
